/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.xml.wrda.core;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import org.jdom2.Document;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

/**
 * WAR entity class with web.xml metadata and whole document
 * @author Mychal
 */
@XStreamAlias("WAR")
public class WAR {

    private Long timeStamp;
    private Document document;

    private String fileName;

    private FilterEntries filters = new FilterEntries();
    @XStreamAlias("filters")
    public static class FilterEntries{
        @XStreamImplicit(itemFieldName = "filter")
        private List<String> filters = new ArrayList<>();

        public List<String> getFilters() {
            return filters;
        }

        public void setFilters(List<String> filters) {
            this.filters = filters;
        }
    }


    private ListenerEntries listeners = new ListenerEntries();
    @XStreamAlias("listeners")
    public static class ListenerEntries{
        @XStreamImplicit(itemFieldName = "listener")
        private List<String> listeners = new ArrayList<>();

        public List<String> getListeners() {
            return listeners;
        }

        public void setListeners(List<String> listeners) {
            this.listeners = listeners;
        }
    }

    public WAR(){
        this.timeStamp = System.currentTimeMillis();
    };


    public Document getDocument() {
        return document;
    }

    public void setDocument(Document document) {
        this.document = document;
    }

    public Long getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(Long timeStamp) {
        this.timeStamp = timeStamp;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public List<String> getFilters() {
        return filters.getFilters();
    }

    public void setFilters(List<String> filters) {
        this.filters.setFilters(filters);
    }

    public List<String> getListeners() {
        return listeners.getListeners();
    }

    public void setListeners(List<String> listeners) {
        this.listeners.setListeners(listeners);
    }

    public String getWebxml() {
        XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
        String output = outputter.outputString(document.getRootElement());
        return output;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        WAR war = (WAR) o;

        if (fileName != null ? !fileName.equals(war.fileName) : war.fileName != null) return false;
        if (timeStamp != null ? !timeStamp.equals(war.timeStamp) : war.timeStamp != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = 7;
        result = 31 * result + (timeStamp != null ? timeStamp.hashCode() : 0);
        result = 31 * result + (fileName != null ? fileName.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        XStream xStream = new XStream();
        xStream.autodetectAnnotations(true);
        xStream.registerConverter(new DocumentConverter());
        return xStream.toXML(this);
    }

    public static class DocumentConverter implements SingleValueConverter{
        @Override
        public String toString(Object o) {
            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            return outputter.outputString((Document)o);
        }

        @Override
        public Object fromString(String s) {
            SAXBuilder builder = new SAXBuilder();
            try {
                Document doc = builder.build(new StringReader(s));
                return doc;
            } catch (JDOMException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public boolean canConvert(Class aClass) {
            return aClass.equals(Document.class);
        }
    }
}
